﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Brainee.Optimization
{
  public class HillClimbingAlgorithm : IOptimizationAlgorithm
  {
#region Properties

    /// <summary>
    /// The strategy to use with this optimization algorithm
    /// </summary>
    /// <remarks>This property must be set before calling HillClimbingAlgorithm.Solve()</remarks>
    public IOptimizationStrategy Strategy;

#endregion
#region ISearchAlgorithm implementation

    public OptimizationSolution Solve (IOptimizationProblem problem)
    {
      if (problem == null)
        throw new ArgumentNullException ("problem");
      if (Strategy == null)
        throw new InvalidOperationException ("A strategy must be defined");

      OptimizationState current = new OptimizationState (problem.InitialState, problem.Evaluate (problem.InitialState));
      UInt32 steps = 0;
      while (true)
      {
        steps++;
        OptimizationState neighbor = Strategy.SelectNeighbor (current, problem);

        if (neighbor.Value <= current.Value)
          break;

        current = neighbor;
      }

      return new OptimizationSolution (current, steps);
    }

#endregion
  }
}
